
(function (window) {

KC.extend({
	trim : function(str) {
		return str.replace(/^\s+|\s+$/g, '');
	},
	escape : function(str) {
		str = str.replace(/&/g, '&amp;');
		str = str.replace(/</g, '&lt;');
		str = str.replace(/>/g, '&gt;');
		str = str.replace(/"/g, '&quot;');
		return str;
	},
	unescape : function(str) {
		str = str.replace(/&lt;/g, '<');
		str = str.replace(/&gt;/g, '>');
		str = str.replace(/&quot;/g, '"');
		str = str.replace(/&amp;/g, '&');
		return str;
	},
	toHex : function(str) {
		function hex(s) {
			s = parseInt(s).toString(16).toUpperCase();
			return s.length > 1 ? s : '0' + s;
		}
		return str.replace(/rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/ig,
			function($0, $1, $2, $3) {
				return '#' + hex($1) + hex($2) + hex($3);
			}
		);
	},
	formatUrl : function(url, mode, host, pathname) {
		if (!mode) return url;
		mode = mode.toLowerCase();
		if (!KC.inArray(mode, ['absolute', 'relative', 'domain'])) return url;
		host = host || location.protocol + '//' + location.host;
		pathname = pathname || (location.pathname.match(/^(\/.*)\//) ? RegExp.$1 : '');
		if (url.match(/^(\w+:\/\/[^\/]*)/)) {
			if (RegExp.$1 !== host) return url;
		} else if (url.match(/^\w+:/)) {
			return url;
		}
		var getRealPath = function(path) {
			var parts = path.split('/');
			paths = [];
			for (var i = 0, len = parts.length; i < len; i++) {
				var part = parts[i];
				if (part == '..') {
					if (paths.length > 0) paths.pop();
				} else if (part !== '' && part != '.') {
					paths.push(part);
				}
			}
			return '/' + paths.join('/');
		};
		if (url.match(/^\//)) {
			url = host + getRealPath(url.substr(1));
		} else if (!url.match(/^\w+:\/\//)) {
			url = host + getRealPath(pathname + '/' + url);
		}
		if (mode == 'relative') {
			var getRelativePath = function(path, depth) {
				if (url.substr(0, path.length) === path) {
					var arr = [];
					for (var i = 0; i < depth; i++) {
						arr.push('..');
					}
					var prefix = '.';
					if (arr.length > 0) prefix += '/' + arr.join('/');
					if (pathname == '/') prefix += '/';
					return prefix + url.substr(path.length);
				} else {
					if (path.match(/^(.*)\//)) {
						return getRelativePath(RegExp.$1, ++depth);
					}
				}
			};
			url = getRelativePath(host + pathname, 0).substr(2);
		} else if (mode == 'absolute') {
			if (url.substr(0, host.length) === host) {
				url = url.substr(host.length);
			}
		}
		return url;
	},
	formatStyle : function(style) {
		style = style.replace(/\s*([^\s]+?)\s*:(.*?)(;|$)/g, function($0, $1, $2) {
			var k = $1.toLowerCase();
			var v = KC.trim($2.toLowerCase());
			v = KC.toHex(v);
			return k + ':' + v + ';';
		});
		return KC.trim(style);
	},
	formatHtml : function(html, urlType) {
		function toHash(tags) {
			var arr = tags.split(/,/);
			var hash = {};
			for (var i = 0, len = arr.length; i < len; i++) {
				hash[arr[i]] = null;
			}
			return hash;
		}
		var singleTagHash = toHash(KC.SINGLE_TAGS);
		var inlineTagHash = toHash(KC.INLINE_TAGS);
		var re = /<(\/)?([\w-:]+)((?:\s+|(?:\s+[\w-:]+)|(?:\s+[\w-:]+=[^\s"'<>]+)|(?:\s+[\w-:]+="[^"]*")|(?:\s+[\w-:]+='[^']*'))*)(\/)?>/g;
		html = html.replace(re, function($0, $1, $2, $3, $4) {
			var startSlash = $1 || '';
			var tagName = $2.toLowerCase();
			var attr = $3 || '';
			var endSlash = $4 ? ' ' + $4 : '';
			if (endSlash === '' && tagName in singleTagHash) endSlash = ' /';
			var nl = '';
			if ((startSlash || endSlash) && !(tagName in inlineTagHash)) nl = '\n';
			if (attr !== '') {
				attr = attr.replace(/\s*([\w-:]+)=([^\s"'<>]+|"[^"]*"|'[^']*')/g, function($0, $1, $2) {
					var key = $1.toLowerCase();
					var val = $2 || '';
					if (val === '') {
						val = '""';
					} else {
						if (key === 'style') {
							val = val.substr(1, val.length - 2);
							val = KC.formatStyle(val);
							if (val === '') return '';
							val = '"' + val + '"';
						}
						if (KC.inArray(key, ['src', 'href'])) {
							if (val.charAt(0) === '"') {
								val = val.substr(1, val.length - 2);
							}
							val = KC.formatUrl(val, urlType);
						}
						if (val.charAt(0) !== '"') val = '"' + val + '"';
					}
					return ' ' + key + '=' + val + ' ';
				});
				attr = attr.replace(/\s+(checked|selected|disabled|readonly)(\s+|$)/ig, function($0, $1) {
					var key = $1.toLowerCase();
					return ' ' + key + '="' + key + '"' + ' ';
				});
				attr = KC.trim(attr);
				attr = attr.replace(/\s+/g, ' ');
				if (attr) attr = ' ' + attr;
				return '<' + startSlash + tagName + attr + endSlash + '>' + nl;
			} else {
				return '<' + startSlash + tagName + endSlash + '>' + nl;
			}
		});
		return html;
	}
});

})(window);